/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef BASE_INCLUDE_BASE_YAML_H
#define BASE_INCLUDE_BASE_YAML_H

#include <string>
#include <vector>
#include <map>
#include <memory>
#include <variant>
#include <stdexcept>

namespace El {
namespace Utils {

/**
 * @brief YAML值类型
 */
class YamlValue {
public:
    using ValueType =
        std::variant<std::string, int, double, bool, std::vector<YamlValue>, std::map<std::string, YamlValue>>;

    YamlValue() = default;
    YamlValue(const ValueType &value) : value_(value) {}

    /**
     * @brief 检查是否为字符串类型
     * @return true表示是字符串类型，false表示不是
     */
    bool IsString() const
    {
        return std::holds_alternative<std::string>(value_);
    }

    /**
     * @brief 检查是否为整型类型
     * @return true表示是整型类型，false表示不是
     */
    bool IsInt() const
    {
        return std::holds_alternative<int>(value_);
    }

    /**
     * @brief 检查是否为双精度浮点型类型
     * @return true表示是双精度浮点型类型，false表示不是
     */
    bool IsDouble() const
    {
        return std::holds_alternative<double>(value_);
    }

    /**
     * @brief 检查是否为布尔型类型
     * @return true表示是布尔型类型，false表示不是
     */
    bool IsBool() const
    {
        return std::holds_alternative<bool>(value_);
    }

    /**
     * @brief 检查是否为数组类型
     * @return true表示是数组类型，false表示不是
     */
    bool IsArray() const
    {
        return std::holds_alternative<std::vector<YamlValue>>(value_);
    }

    /**
     * @brief 检查是否为Map类型
     * @return true表示是Map类型，false表示不是
     */
    bool IsMap() const
    {
        return std::holds_alternative<std::map<std::string, YamlValue>>(value_);
    }

    /**
     * @brief 获取字符串值
     * @return 字符串值
     */
    std::string AsString() const
    {
        return std::get<std::string>(value_);
    }

    /**
     * @brief 获取整型值
     * @return 整型值
     */
    int AsInt() const
    {
        return std::get<int>(value_);
    }

    /**
     * @brief 获取双精度浮点型值
     * @return 双精度浮点型值
     */
    double AsDouble() const
    {
        return std::get<double>(value_);
    }

    /**
     * @brief 获取布尔型值
     * @return 布尔型值
     */
    bool AsBool() const
    {
        return std::get<bool>(value_);
    }

    /**
     * @brief 获取数组值
     * @return 数组值引用
     */
    const std::vector<YamlValue> &AsArray() const
    {
        return std::get<std::vector<YamlValue>>(value_);
    }

    /**
     * @brief 获取Map值
     * @return Map值引用
     */
    const std::map<std::string, YamlValue> &AsMap() const
    {
        return std::get<std::map<std::string, YamlValue>>(value_);
    }

    /**
     * @brief 通过路径获取值
     * @param path 路径字符串 (例如: "server.host" 或 "users[0].name")
     * @return 对应的YamlValue
     * @throw std::runtime_error 如果路径无效或键不存在
     */
    YamlValue Get(const std::string &path) const
    {
        if (path.empty()) {
            return *this;
        }

        if (!IsMap()) {
            throw std::runtime_error("Cannot get path from non-map value");
        }

        size_t pos = path.find('.');
        std::string key = pos == std::string::npos ? path : path.substr(0, pos);

        const auto &map = AsMap();
        auto it = map.find(key);
        if (it == map.end()) {
            throw std::runtime_error("Key not found: " + key);
        }

        if (pos == std::string::npos) {
            return it->second;
        }

        return it->second.Get(path.substr(pos + 1));
    }

private:
    ValueType value_;
};

/**
 * @brief YAML解析器
 */
class YamlParser {
public:
    YamlParser() = default;
    ~YamlParser() = default;

    /**
     * @brief 从文件加载YAML
     * @param filename YAML文件路径
     * @return true表示加载成功，false表示失败
     */
    bool LoadFromFile(const std::string &filename);

    /**
     * @brief 从字符串加载YAML
     * @param content YAML字符串内容
     * @return true表示加载成功，false表示失败
     */
    bool LoadFromString(const std::string &content);

    /**
     * @brief 获取根节点
     * @return 根节点YamlValue引用
     */
    const YamlValue &GetRoot() const
    {
        return root_;
    }

    /**
     * @brief 通过路径获取值
     * @param path 路径字符串 (例如: "server.host" 或 "users[0].name")
     * @return 对应的YamlValue
     */
    YamlValue Get(const std::string &path) const;

    /**
     * @brief 获取错误信息
     * @return 错误信息字符串
     */
    std::string GetLastError() const
    {
        return lastError_;
    }

private:
    YamlValue root_;
    std::string lastError_;

    // 内部解析方法
    bool Parse(const std::string &content);
    YamlValue ParseValue(std::string &line);
    int GetIndentation(const std::string &line) const;
    std::pair<std::string, std::string> SplitKeyValue(const std::string &line) const;
};

} // namespace Utils
} // namespace El

#endif // BASE_INCLUDE_BASE_YAML_H